<?php
declare (strict_types=1);

namespace app\service\logic\common\chat;

use app\exception\LogicException;
use app\model\communal\AdminModel;
use app\model\communal\ImFriendsExpertModel;
use app\model\communal\ImMessageModel;
use app\model\communal\ImFriendsModel;
use app\model\communal\UserModel;
use app\service\logic\BaseService;
use app\service\logic\common\user\ExpertService;
use Carbon\Carbon;
use think\facade\Db;
use think\Model;
use think\db\exception\DbException;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;

final class ChatService extends BaseService
{
    protected string $modelClassName = 'ImMessageModel';

    /**
     * @param $params
     * @param array $search_fields
     * @param array $search
     * @param array $with
     * @param null $eachCall
     * @param bool $isPage
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getList($params, array $search_fields = [], array $search = [], $with = [], $eachCall = null, $isPage = true)
    {
        $order = $this->orderByParams($params, 'created_at', 'asc');
        $query = ImMessageModel::field(ImMessageModel::$column)
            ->with($with)
            ->withSearch($search_fields, $search);

        if ($isPage) {
            list($page, $page_size) = $this->pageByParams($params);
            $query->page($page, $page_size);
        }

        return $query->order($order)
            ->select()
            ->each(function ($model) use ($params, $search) {
                // 默认头像
                $defaultAvatar = config('domain.api') . '/static/web/images/default_avatar.png';
                // 框架多态不支持移除软删除 坐等-~-
                if (is_null($model['sender'])) {
                    $model['sender_name'] = '已注销';
                    $model['sender_mobile'] = '';
                    $model['sender_avatar'] = $defaultAvatar;
                } else {
                    $model['sender_name'] = $model['sender']['name'];
                    $model['sender_mobile'] = $model['sender']['mobile'];
                    $model['sender_avatar'] = empty($model['sender']['avatar']) ? $defaultAvatar : $model['sender']['avatar'];
                }

                if (is_null($model['receiver'])) {
                    $model['receiver_name'] = '已注销';
                    $model['receiver_mobile'] = '';
                    $model['receiver_avatar'] = $defaultAvatar;
                } else {
                    $model['receiver_name'] = $model['receiver']['name'];
                    $model['receiver_mobile'] = $model['receiver']['mobile'];
                    $model['receiver_avatar'] =  empty($model['receiver']['avatar']) ? $defaultAvatar : $model['receiver']['avatar'];
                }

                if (
                    ImMessageModel::TYPE_THREE == $model['type']
                    || ImMessageModel::TYPE_FOUR == $model['type']
                ) {
                    $model['content'] = json_decode($model['content'], true);
                }

                // 消息的左右
                if (ImMessageModel::$morph[$search['login_type']] == $model['sender_type'] && $search['login_id'] == $model['sender_id']) {
                    $model['is_show_right'] = ImMessageModel::IS_SHOW_RIGHT_ONE;
                } else {
                    $model['is_show_right'] = ImMessageModel::IS_SHOW_RIGHT_TWO;
                }
                $model['sender_type'] = ImMessageModel::$morphMap[$model['sender_type']];
                $model['receiver_type'] = ImMessageModel::$morphMap[$model['receiver_type']];

                unset($model['sender']);
                unset($model['receiver']);
            })
            ->toArray();
    }

    /**
     * 聊起来
     *
     * @param $params
     * @return ImMessageModel|Model
     * @throws LogicException
     */
    public function create($params)
    {
        // 聊天标识
        $chatMark = $this->getChatMark($params);
        $params['chat_mark'] = $chatMark;
        $params['sender_type'] = ImMessageModel::$morph[$params['sender_type']];
        $params['receiver_type'] = ImMessageModel::$morph[$params['receiver_type']];

        return ImMessageModel::create($params);
    }

    /**
     * 获取一对一聊天标识
     *
     * @param $params
     * @param string $typeColumn1
     * @param string $typeColumn2
     * @param string $idColumn1
     * @param string $idColumn2
     * @param bool $friend
     * @return string
     * @throws LogicException
     */
    public function getChatMark(
        $params,
        $typeColumn1 = 'sender_type', $typeColumn2 = 'receiver_type',
        $idColumn1 = 'sender_id', $idColumn2 = 'receiver_id',
        $friend = true
    )
    {
        $chatMark = '';
        if (ImMessageModel::MORPH_TYPE_ONE == $params[$typeColumn1] && ImMessageModel::MORPH_TYPE_TWO == $params[$typeColumn2]) {
            // 发送人为员工, 接收人为用户
            $adminId = $params[$idColumn1];
            $userId = $params[$idColumn2];
            !$friend || $this->addFriendsUserAdmin($adminId, $userId);
            $chatMark = 'Admin_' . $adminId . '_User_' . $userId;
        } else if (ImMessageModel::MORPH_TYPE_TWO == $params[$typeColumn1] && ImMessageModel::MORPH_TYPE_ONE == $params[$typeColumn2]) {
            // 发送人为用户, 接收人为员工
            $userId = $params[$idColumn1];
            $adminId = $params[$idColumn2];
            !$friend || $this->addFriendsUserAdmin($adminId, $userId);
            $chatMark = 'Admin_' . $adminId . '_User_' . $userId;
        }
        // ...

        if (empty($chatMark)) {
            throw new LogicException(lang('communal.chat mark exception'));
        }
        return $chatMark;
    }

    /**
     * 记录用户|客服好友表
     *
     * @param $adminId
     * @param $userId
     * @return bool
     */
    public function addFriendsUserAdmin($adminId, $userId)
    {
        $result = true;
        $data = ['user_id' => $userId, 'admin_id' => $adminId];
        $userAdmin = ImFriendsModel::where($data)->findOrEmpty();
        if (!$userAdmin->isExists()) {
            $result = $userAdmin->save($data);
        }

        return $result;
    }

    /**
     * 专家私聊
     *
     * @param $params
     * @return mixed
     * @throws LogicException
     */
    public function chat($params)
    {
        $params['id'] = $params['expert_id'];
        // 获取专家所属客服
        $expert = invoke(ExpertService::class)->getSimpleDetail($params);
        if (empty($expert['customer_id'])) {
            throw new LogicException('暂未分配顾问');
        }
        unset($params['id']);

        // 添加用户专家好友
        // 发送私聊消息
        Db::connect('communal')->transaction(function () use ($params, $expert, &$result) {
            $params['receiver_id'] = $expert['customer_id'];
            $params['receiver_type'] = ImMessageModel::MORPH_TYPE_ONE;
            $params['type'] = ImMessageModel::TYPE_FOUR;
            $params['content'] = json_encode($expert, JSON_UNESCAPED_UNICODE);
            invoke(ChatService::class)->create($params);
            $result = $this->addFriendsUserExpert($expert['id'], $params['user_id']);
        });

        return $result;
    }

    /**
     * 记录用户|专家好友表
     *
     * @param $expertId
     * @param $userId
     * @return bool
     */
    public function addFriendsUserExpert($expertId, $userId)
    {
        $data = ['user_id' => $userId, 'expert_id' => $expertId];
        $model = ImFriendsExpertModel::where($data)->findOrEmpty();
        if (!$model->isExists()) {
            $result = $model->save($data);
        } else {
            $result = $model->save(['updated_at' => Carbon::now()->timestamp]);
        }

        return $result;
    }

    /**
     * 更新
     *
     * @param $id
     * @param $params
     * @return bool
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function update($id, $params)
    {
        $role = $this->getSimpleDetail($id);
        $params['state'] = $params['state'] == true ? ImMessageModel::STATE_ONE : ImMessageModel::STATE_TWO;

        return $role->save($params);
    }

    /**
     * 已读
     *
     * @param $params
     * @param array $search_fields
     * @param array $search
     * @return bool
     */
    public function already($params, $search_fields = [], $search = [])
    {
        return ImMessageModel::withSearch($search_fields, $search)
            ->save(['state' => ImMessageModel::STATE_TWO]);
    }

    /**
     * 类型变更
     *
     * @param $params
     * @return array|mixed|Model
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function type($params)
    {
        $model = $this->getSimpleDetail($params);
        $model->save(['type' => $params['type']]);
        return $model;
    }

    /**
     * 是否存在未读, 未读数量
     *
     * @param $senderId
     * @param $senderType
     * @param $receiverId
     * @param $receiverType
     * @param $state
     * @return int
     */
    public function getNumberByState($senderId, $senderType, $receiverId, $receiverType, $state)
    {
        return ImMessageModel::withSearch($this->getSearchColumn(), [
            'sender_id' => $senderId,
            'sender_type' => $senderType,
            'receiver_id' => $receiverId,
            'receiver_type' => $receiverType,
            'state' => $state
        ])->count();
    }

}
